# -*- coding: utf-8 -*-

import json
import random
from decimal import Decimal

from common import orm
from common.account.db import account
from common.account.model.account import Account
from common.pay.db import get_today_recharge
from common.transaction.db import create_sharding_transaction
from common.transaction.model import (TRANSACTION_STATUS,
                                      TRANSACTION_TYPE)
from common.utils import exceptions as err
from common.utils import track_logging
from common.utils.decorator import sql_wrapper
from common.utils.respcode import StatusCode
from common.utils.tz import today_str
from .recharge_red_envelope_model import RedEnvelopeRecord, RED_ENVELOPE_TYPE

_LOGGING = track_logging.getLogger(__name__)


def get_winners_list(limit=50):
    return RedEnvelopeRecord.query.order_by(-RedEnvelopeRecord.id).limit(limit).all()


def add_winner_info(user_id, red_envelope_type, amount, auto_commit=False):
    assert red_envelope_type in RED_ENVELOPE_TYPE.values()
    user = account.get_account(user_id, use_cache=True)
    if not user:
        raise err.DataError(status=StatusCode.INVALID_USER)

    record = RedEnvelopeRecord()
    record.user_id = user.id
    record.user_name = user.user_name
    record.amount = amount
    record.red_envelope_type = red_envelope_type
    record.date = today_str()
    record.save(auto_commit=auto_commit)


def had_open_envelope(user_id, red_envelope_type):
    if not user_id:
        return False
    return orm.session.query(RedEnvelopeRecord).filter(RedEnvelopeRecord.user_id == user_id,
                                                       RedEnvelopeRecord.red_envelope_type == red_envelope_type,
                                                       RedEnvelopeRecord.date == today_str()).count()


def get_all_envelope_status(user_id):
    result = []
    for envelope_id in sorted(RED_ENVELOPE_TYPE.values()):
        result.append(
            dict(id=envelope_id, name=RED_ENVELOPE_TYPE.get_label(envelope_id),
                 had_open=had_open_envelope(user_id, envelope_id)))
    return result


def get_activity_recharge_count(user_id):
    if not user_id:
        return 0
    return get_today_recharge(user_id, [])


awards = [88, 10, 5, 2, 1, 0.5, 0.2, 0.1]
probabilities = [0.01, 0.03, 0.06, 0.1, 0.2, 0.2, 0.2, 0.2]

RED_ENVELOPE_PROBABILITY = {
    RED_ENVELOPE_TYPE.CD1: ([1, 2, 3, 4, 5, 6, 7, 8], [.15, .15, .15, .15, .1, .1, .1, .1]),
    RED_ENVELOPE_TYPE.CD2: ([8, 18, 28, 38, 48, 58, 68, 88], [.15, .15, .15, .15, .1, .1, .1, .1]),
    RED_ENVELOPE_TYPE.CD3: ([88, 128, 188, 228, 288], [.2, .2, .2, .2, .2]),
    RED_ENVELOPE_TYPE.CD4: ([188, 288, 388, 488, 588], [.2, .2, .2, .2, .2]),
    RED_ENVELOPE_TYPE.CD5: ([388, 688, 988, 1288, 1588], [.2, .2, .2, .2, .2]),
    RED_ENVELOPE_TYPE.CD6: ([888, 1288, 1888, 2888, 3888], [.2, .2, .2, .2, .2]),
}

RED_ENVELOPE_THRESHOLD = {
    RED_ENVELOPE_TYPE.CD1: 188,
    RED_ENVELOPE_TYPE.CD2: 1888,
    RED_ENVELOPE_TYPE.CD3: 8888,
    RED_ENVELOPE_TYPE.CD4: 18888,
    RED_ENVELOPE_TYPE.CD5: 38888,
    RED_ENVELOPE_TYPE.CD6: 88888,
}


def rand_pick(seq, probabilities):
    x = random.uniform(0, 1)
    cumprob = 0.0
    for item, item_pro in zip(seq, probabilities):
        cumprob += item_pro
        if x < cumprob:
            break
    return item


@sql_wrapper
def open_envelope(user_id, red_envelope_type):
    if not red_envelope_type or not user_id:
        raise err.DataError(status=StatusCode.PARAM_REQUIRED)

    user = Account.query.filter(
        Account.id == user_id).with_for_update().first()

    if not user:
        raise err.DataError(status=StatusCode.INVALID_USER)

    today_recharge = get_activity_recharge_count(user_id)
    threshold = RED_ENVELOPE_THRESHOLD[red_envelope_type]

    if today_recharge < threshold:
        raise err.DataError(u'未达到活动条件')

    if had_open_envelope(user_id, red_envelope_type):
        raise err.DataError(u'已领取改红包')

    award = rand_pick(*RED_ENVELOPE_PROBABILITY[red_envelope_type])
    _LOGGING.info("open_envelope {} {} {} {}".format(user_id, today_recharge, red_envelope_type, award))
    add_winner_info(user_id, red_envelope_type, award)

    user.balance += award
    create_sharding_transaction(user_id, {
        'type': TRANSACTION_TYPE.PAY_BONUS,
        'title': u'充值红包奖励',
        'extend': json.dumps({'red_envelope_type': red_envelope_type}, ensure_ascii=False),
        'price': award,
        'balance': float(user.balance),
        'status': TRANSACTION_STATUS.DONE,
    })
    user.save(auto_commit=False)

    orm.session.commit()

    return award
